package org.lmib.abt.checkers;
/*
 * Copyright (c) 1996/1997 F. Di Fabio
 * All rights reserved.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc., 675
 * Mass Ave, Cambridge, MA 02139, USA.
 */


import java.util.Vector;
import java.util.Stack;

class State {
  Box[] status;
  Vector listOfValidMoves;
  Stack stateBackup;

public State() {

    status = new Box[32];
    listOfValidMoves = new Vector(30,10);
    stateBackup = new Stack();
    int i;
    for(i=0;i<32;i++) {
    	status[i] = new Box(i);
    }
	
    status[0].setBox(CheckersGlobal.MANBLACK,Box.NOBOX,Box.NOBOX,Box.NOBOX,status[4]);
    status[1].setBox(CheckersGlobal.MANBLACK,Box.NOBOX,Box.NOBOX,status[4],status[5]);
    status[2].setBox(CheckersGlobal.MANBLACK,Box.NOBOX,Box.NOBOX,status[5],status[6]);
    status[3].setBox(CheckersGlobal.MANBLACK,Box.NOBOX,Box.NOBOX,status[6],status[7]);
    status[4].setBox(CheckersGlobal.MANBLACK,status[0],status[1],status[8],status[9]);
    status[5].setBox(CheckersGlobal.MANBLACK,status[1],status[2],status[9],status[10]);
    status[6].setBox(CheckersGlobal.MANBLACK,status[2],status[3],status[10],status[11]);
    status[7].setBox(CheckersGlobal.MANBLACK,status[3],Box.NOBOX,status[11],Box.NOBOX);
    status[8].setBox(CheckersGlobal.MANBLACK,Box.NOBOX,status[4],Box.NOBOX,status[12]);
    status[9].setBox(CheckersGlobal.MANBLACK,status[4],status[5],status[12],status[13]);
    status[10].setBox(CheckersGlobal.MANBLACK,status[5],status[6],status[13],status[14]);
    status[11].setBox(CheckersGlobal.MANBLACK,status[6],status[7],status[14],status[15]);
    status[12].setBox(CheckersGlobal.EMPTYBLUE,status[8],status[9],status[16],status[17]);
    status[13].setBox(CheckersGlobal.EMPTYBLUE,status[9],status[10],status[17],status[18]);
    status[14].setBox(CheckersGlobal.EMPTYBLUE,status[10],status[11],status[18],status[19]);
    status[15].setBox(CheckersGlobal.EMPTYBLUE,status[11],Box.NOBOX,status[19],Box.NOBOX);
    status[16].setBox(CheckersGlobal.EMPTYBLUE,Box.NOBOX,status[12],Box.NOBOX,status[20]);
    status[17].setBox(CheckersGlobal.EMPTYBLUE,status[12],status[13],status[20],status[21]);
    status[18].setBox(CheckersGlobal.EMPTYBLUE,status[13],status[14],status[21],status[22]);
    status[19].setBox(CheckersGlobal.EMPTYBLUE,status[14],status[15],status[22],status[23]);
    status[20].setBox(CheckersGlobal.MANWHITE,status[16],status[17],status[24],status[25]);
    status[21].setBox(CheckersGlobal.MANWHITE,status[17],status[18],status[25],status[26]);
    status[22].setBox(CheckersGlobal.MANWHITE,status[18],status[19],status[26],status[27]);
    status[23].setBox(CheckersGlobal.MANWHITE,status[19],Box.NOBOX,status[27],Box.NOBOX);
    status[24].setBox(CheckersGlobal.MANWHITE,Box.NOBOX,status[20],Box.NOBOX,status[28]);
    status[25].setBox(CheckersGlobal.MANWHITE,status[20],status[21],status[28],status[29]);
    status[26].setBox(CheckersGlobal.MANWHITE,status[21],status[22],status[29],status[30]);
    status[27].setBox(CheckersGlobal.MANWHITE,status[22],status[23],status[30],status[31]);
    status[28].setBox(CheckersGlobal.MANWHITE,status[24],status[25],Box.NOBOX,Box.NOBOX);
    status[29].setBox(CheckersGlobal.MANWHITE,status[25],status[26],Box.NOBOX,Box.NOBOX);
    status[30].setBox(CheckersGlobal.MANWHITE,status[26],status[27],Box.NOBOX,Box.NOBOX);
    status[31].setBox(CheckersGlobal.MANWHITE,status[27],Box.NOBOX,Box.NOBOX,Box.NOBOX);
}

public int getPieceAt(int i) {

    return status[i].getPiece();
}

public void save() {
  int idBoxArray[] = new int[32];
  int i;
  
    for(i=0;i<32;i++) {
    	idBoxArray[i] = status[i].getPiece();
    }
    stateBackup.push(idBoxArray);
}

public void restore() {
  int idBoxArray[];
  int i;

    idBoxArray = (int[])stateBackup.pop();
    for(i=0;i<32;i++) {
    	status[i].setPiece(idBoxArray[i]);
    }
}

public void doMove(Move move, boolean makeKing) {
  int i;
  
    //esegue la mossa spostando i pezzi
    while(move != Move.NOMOVE) {
    	if(move.isJump) {
		    move.to.setPiece(move.from.getPiece());
		    move.from.near[move.direction].setPiece(CheckersGlobal.EMPTYBLUE);
		    move.from.setPiece(CheckersGlobal.EMPTYBLUE);
		}
		else {
		    move.to.setPiece(move.from.getPiece());
		    move.from.setPiece(CheckersGlobal.EMPTYBLUE);
		}
		move = move.toNextJump;
    }
    //crea le nuove dame se c'è bisogno
    if(makeKing) {
    	for(i=0;i<4;i++) {
		    if(status[i].getPiece() == CheckersGlobal.MANWHITE) {
		    	status[i].setPiece(CheckersGlobal.KINGWHITE);
		    }
    	}
		for(i=28;i<32;i++) {
		    if(status[i].getPiece() == CheckersGlobal.MANBLACK) {
		    	status[i].setPiece(CheckersGlobal.KINGBLACK);
		    }
		}
    }
}

public Vector validMoves(int color) {
  int i;
  int j;
  int k;
  boolean thereAreJumps = false;
  boolean end = false;
  int numJumps;
  int maxPriority = 0;
  int newPriority;
  Vector listOfJumps = new Vector(4);
  Move move;
  Move jump;
  Move endMove;
  int maxPiece;
  Vector headOfJumps = new Vector(4);
  Vector curOfJumps = new Vector(4);
  Vector removedJumps = new Vector(4);
  int numOfJump;
  
    //tolgo le mosse trovate precedentemente
    listOfValidMoves.removeAllElements();		
    //trova tutte le mosse valide e non
    for(i=0;i<32;i++) {
    	status[i].findMoves(color,listOfValidMoves);
    }
    //verifica se c'è un salto
    i = 0;
    while((! end) && (i < listOfValidMoves.size())) {
    	if(((Move)listOfValidMoves.elementAt(i)).isJump) { //c'è un salto elimino tutte le mosse senza salti
		    thereAreJumps = true;
		    end = true;
		    j = 0;
		    while(j < listOfValidMoves.size()) {
				if(! ((Move)listOfValidMoves.elementAt(j)).isJump) {
				    listOfValidMoves.removeElementAt(j);
				}
				else {
				    j++;
				}
		    }
		}
		else { 
		    i++;
		}
    }
    if(thereAreJumps) {
    	while(thereAreJumps) {
    		thereAreJumps = false;
    		numJumps = listOfValidMoves.size();
    		for(j=0;j<numJumps;j++) {
    			this.save();
    			move = (Move)listOfValidMoves.elementAt(j);
    			this.doMove(move,false);
    			endMove = move;
    			while(endMove.toNextJump != Move.NOMOVE) {
    				endMove = endMove.toNextJump;
    			}
    			status[endMove.to.idBox].findMoves(color,listOfJumps);
    			for(k=0;k<listOfJumps.size();k++) {
    				if(((Move)listOfJumps.elementAt(k)).isJump) {
    					thereAreJumps = true;
    					jump = move.copy();
    					jump.addJump((Move)listOfJumps.elementAt(k));
    					listOfValidMoves.addElement(jump);
    				}
    			}
    			listOfJumps.removeAllElements();
    			this.restore();
    		}
    		if(thereAreJumps) {
    			for(j=0;j<numJumps;j++) {
    				listOfValidMoves.removeElementAt(0);
    			}
    		}
    	}  //fine while thereareJumps
			
    	for(i=0;i<listOfValidMoves.size();i++) {
    		newPriority = ((Move)listOfValidMoves.elementAt(i)).setPriority();
    		if(newPriority > maxPriority) {
    			maxPriority = newPriority;
    		}
    	}
			
    	j = 0;
    	for(i=0;i<listOfValidMoves.size();i++) {
    		if(((Move)listOfValidMoves.elementAt(j)).priority < maxPriority) { 
    			listOfValidMoves.removeElementAt(j);
    		}
    		else {
    			j++;
    		}
    	}
    }

    return ((Vector)listOfValidMoves.clone());
}

public int value(int computerColor) {
  int black = 0;
  int white = 0;
  int i;
  
    for(i=0;i<32;i++) {
    	switch (status[i].getPiece()) {
		    case CheckersGlobal.MANWHITE :
		    	white++;
		    break;
		    case CheckersGlobal.MANBLACK :
		    	black++;
		    break;
		    case CheckersGlobal.KINGWHITE :
		    	white+=4;
		    break;
		    case CheckersGlobal.KINGBLACK :
		    	black+=4;
		    break;
		}
    }
    if(computerColor == CheckersGlobal.WHITE) { 
    	return (white - black);
    }
    return (black - white);		
}
}
